package org.mysfit.ctp4j.core.service.impl;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.mysfit.ctp4j.core.service.FkDataService;
import org.mysfit.ctp4j.core.service.MarketService;
import org.mysfit.ctp4j.core.service.TradeService;
import org.mysfit.ctp4j.infra.entity.CtpData;
import org.mysfit.ctp4j.infra.entity.SkData;
import org.mysfit.ctp4j.infra.mapper.SkDataMapper;
import org.mysfit.ctp4j.infra.utils.TradeDataUtils;
import org.mysfit.ctp4j.infra.utils.TradeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import ctp.thosttraderapi.CThostFtdcDepthMarketDataField;

/**
 * <p>
 * sk 服务实现类
 * </p>
 *
 * @author long.gf
 * @since 2022-12-02
 */
@Service
public class MarketServiceImpl implements MarketService {
	
	@Autowired
	private SkDataMapper skMapper;

	@Autowired
	private FkDataService fkService;
	
	@Autowired
	private TradeService tradeService;
	
	private static 	ThreadPoolExecutor exe;
	
	static {
		exe=new ThreadPoolExecutor(10, 10,
                10L, TimeUnit.MINUTES,
                new LinkedBlockingQueue<Runnable>());
		exe.allowCoreThreadTimeOut(true);
		Runtime.getRuntime().addShutdownHook(new Thread(()-> {
			exe.shutdown();
		}));
	}
	
	private void setFidx(CtpData ctp) {
		Integer fidx = new Integer(0);
		String fKey = ctp.getFid()+ctp.getFday();
		if(null != TradeUtils.FIDX_MAP.get(fKey)) {
			fidx = TradeUtils.FIDX_MAP.get(fKey) ;
		}
		ctp.setFidx(fidx);
		fidx+=1;
		TradeUtils.FIDX_MAP.put(fKey, fidx);
	}
	
	private  void addCtp(CThostFtdcDepthMarketDataField data) {
		if(data.getVolume() == 0) {
			return ;
		}
		String fid = data.getInstrumentID();
		String day = data.getTradingDay().substring(0,4)+"-"+data.getTradingDay().substring(4,6)+"-"+data.getTradingDay().substring(6);
		String time = data.getUpdateTime();
		CtpData ctp = new CtpData();
		ctp.setFid(fid);
		ctp.setFtime(day + " " + time +"."+data.getUpdateMillisec());
		ctp.setFday(Integer.parseInt(day.replaceAll("-","")));
		ctp.setFp(data.getLastPrice());
		ctp.setFa(data.getTurnover());
		ctp.setFv(data.getVolume());
		this.setFidx(ctp);
		skMapper.insertCtp(ctp);
	}
	
	public void addSk(CThostFtdcDepthMarketDataField data) {
		SkData sk = new SkData();
		String fid = data.getInstrumentID();
		String day = data.getTradingDay().substring(0,4)+"-"+data.getTradingDay().substring(4,6)+"-"+data.getTradingDay().substring(6);
		String time = data.getUpdateTime();
		sk.setFtime(day + " " + time);
		int millisec = data.getUpdateMillisec();
		if(millisec == 0) {
			if(!TradeDataUtils.getInstance(fkService, tradeService).checkUk(fid, day, time)) {
				return ;
			}
			String volKey = "vol" + "_"+fid ;
			String amtKey = "amt" + "_"+fid ;
			Double lastVol = null == TradeDataUtils.LAST_MK_MAP.get(volKey) ? Double.valueOf(0) : TradeDataUtils.LAST_MK_MAP.get(volKey);
			Double lastAmount = null == TradeDataUtils.LAST_MK_MAP.get(amtKey) ? Double.valueOf(0) : TradeDataUtils.LAST_MK_MAP.get(amtKey);
			sk.setFid(fid);
			sk.setFp(data.getLastPrice());
			sk.setFv(data.getVolume() - lastVol);
			sk.setFa(data.getTurnover() - lastAmount);
			sk.setTotalFv(data.getVolume());
			sk.setTotalFa(data.getTurnover());
			skMapper.insert(sk);
			TradeDataUtils.LAST_MK_MAP.put(volKey, new Double(data.getVolume()));
			TradeDataUtils.LAST_MK_MAP.put(amtKey, data.getTurnover());
			TradeDataUtils.getInstance(fkService, tradeService).refershSk(sk);
			TradeDataUtils.getInstance(fkService, tradeService).insertFk(sk);
			TradeDataUtils.getInstance(fkService, tradeService).refershFk(sk);
			exe.execute(new Runnable() {
				@Override
				public void run() {
					 tradeService.doPolyOrder(sk);
				}
			});
		}
	}
	
	@Override
	public void saveData(CThostFtdcDepthMarketDataField data)  {
		if (data != null) {
			this.addCtp(data);
         } 
	}
	
}
